//*****************************************************************************
// eventQueue.h
//
// Copyright 2009 by Magpie, http://www.magpieti.com
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//*****************************************************************************

#ifndef EVENT_QUEUE_H
#define EVENT_QUEUE_H

// Size of queue, defines the number of events the device can
// queue at any given time. Should more events be sent than can be
// queued, excess events will be dropped based upon start times (events
// with start times further in the future will be dropped). As space
// becomes available, requests will be made for events that were
// dropped.
#define eventQueue_SZ 5

// Typedef to simplify signature of the sendEventStatusFunction
// argument of the init routine
typedef void (*eventStatusFunction)(int32u eventId,
                           int8u eventStatus,
                           int32u startTime,
                           int16u duration);

// typedef for signature of function to request that up to count events that
// occur after effective time be sent to our device. This is required because
// we have a limited queue size.

typedef void (*requestScheduledEventsFunction)(int32u effectiveTime,
                                               int8u count);

//*****************************************************************************
// initEventQueue
//
// Initializes event arrays and counts and injects functional dependencies. 
// Since the system may already be in an operational state, after 
// initialization, query for any scheduled events.
//
// In order to keep this module indendent and reusable across multiple devices 
// and also to facilitate testing, the vast majority of device specific 
// dependencies are "injected" into the module during initialization. These 
// dependencies take the form of functions supplied.
//
// enableEventFunction
//    Called at the start of an event to allow a device to perform any specific
//    actions required for the event.
// disableEventFunction
//    Called at the end of an event to allow a device to perform any specific 
//    actions required for the event. If adjacentToStart is TRUE, then another 
//    event is scheduled to start immediately after this event ends. The device 
//    should take step to ensure that spikes or gaps in operation do not occur 
//    in this situation.
// sendEventStatusFunction
//    Called to initiate a Report Event Status message.
// reqEventFunction
//    Called to notify client that up to count events that occur after
//    effective time may be sent to our device. This is required because we
//    have a limited queue size.
//
//*****************************************************************************
void initEventQueue(void (*enableEventFunction)(int32u eventId),
                    void (*disableEventFunction)(int32u eventId,
                          boolean adjacentToStart),
                    eventStatusFunction sendEventStatusFunction,
                    requestScheduledEventsFunction reqEventFunction);

//*****************************************************************************
// addNewEventToQueue
//
// Performs input validation on the request and queues the event for execution.
//
// Validation of event includes:
//
//    Duration is in range [1,1440]. Upper range is per Zigebee spec. If 
//    greater than this value, the event is rejected with a status 
//    EVENT_REJECTED sent to the requestor. A duration of zero, while allowed 
//    by the spec, is interpreted as an expired event, since the event is 
//    essentially complete when received. This is not per spec, but is an 
//    interpretation of the spec based on other use cases.
//
//    Start time is checked for a value of 0xffffffff. If it is equal to this 
//    value, the event is rejected with a status of EVENT_REJECTED per the spec.
//
//    If the event ID is a duplicate of a value already received, the request is
//    silently rejected per the spec.
//
//    The start time and duration are combined to validate that the event can be
//    constructed in a manner that results in a non-zero duration event with an
//    effective start time that occurs before the requested end time. Should this
//    condition not be true, the event should be flagged as expired per the spec.
//    Specific checks taken include (see spec for definitions of terms used):
//
//        1.) Duration is non-zero
//        2.) End time occurs in the future (after current time)
//        3.) Start time occurs before end time
//
//    If any of the above are not true, the event is rejected.
//
//*****************************************************************************
void addNewEventToQueue(int32u eventId,
                            int32u startTime,
                            int16u duration,
                            int32u currentTime);

//*****************************************************************************
// processEvents
//
// Using the supplied time, review the event queue for any events that are 
// starting or ending. This routine should be called periodically (typically 
// once per second) for proper operation of this module.
//
//*****************************************************************************
void processEvents(int32u currentTime);

#endif //EVENT_QUEUE_H
